﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using Bilibili.Model.Common;
using Bilibili.Model.Danmaku;
using Bilibili.Common.Log;
using Bilibili.WebClient.Common;
using Bilibili.Model.Resource;
using Newtonsoft.Json.Linq;
using System.Linq;
using PCLUntils.Objects;
using PCLUntils.Json;

namespace Bilibili.WebClient.Api
{
    public sealed class DanmakuClient : ClientBase
    {
        public async Task<string> GetBiliBili(long cid)
        {
            try
            {
                string url = string.Format("https://api.bilibili.com/x/v1/dm/list.so?oid={0}", cid);
                return await ApiClient.GetResultsDeflate(url);
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("GetBiliBili", ex);
                return string.Empty;
            }
        }
        public async Task<string> GetBiliBili(long cid, int segmentIndex)
        {
            try
            {
                string url = $"http://api.bilibili.com/x/v2/dm/list/seg.so?type=1&oid={cid}&segment_index={segmentIndex}";
                return await ApiClient.GetResultsDeflate(url);
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("GetBiliBili", ex);
                return string.Empty;
            }
        }
        public async Task<ReturnModel<JObject>> Send(string aId, string cid, int modeInt, int color, string text, long position)
        {
            try
            {
                ApiInfo apiInfo = new ApiInfo("https://api.bilibili.com/x/v2/dm/post", $"&aid={aId}&oid={cid}", true);
                string data = $"pool=0&rnd={ApiProvider.Instance.TimeSpanSeconds}&oid={cid}&fontsize=25&msg={Uri.EscapeDataString(text)}&mode={modeInt}&progress={position}" +
                    $"&color={color}&plat=2&screen_state=0&from=861&type=1";
                string result = await ApiClient.PostResults(apiInfo, data);
                var obj = result.ToJObject();
                return BuildSuccessResult(obj);
            }
            catch (Exception ex)
            {
                return BuildExceptionResult<JObject>(ex);
            }
        }
        public async Task<List<DanmakuModel>> ParseBiliBili(FileInfo file)
        {
            using var stream = file.OpenRead();
            var bytes = new byte[stream.Length];
            await stream.ReadAsync(bytes, 0, bytes.Length);
            string danmuStr = Encoding.UTF8.GetString(bytes);
            return ParseBiliBiliXml(danmuStr);
        }
        public List<DanmakuModel> ParseBiliBiliXml(string xmlStr)
        {
            List<DanmakuModel> danmakus = new List<DanmakuModel>();
            try
            {
                XmlDocument xdoc = new XmlDocument();
                xmlStr = Regex.Replace(xmlStr, @"[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]", string.Empty);
                xdoc.LoadXml(xmlStr);
                foreach (XmlNode item in xdoc.DocumentElement.ChildNodes)
                {
                    if (item.Attributes["p"] != null)
                    {
                        try
                        {
                            string node = item.Attributes["p"].Value;
                            string[] danmaku = node.Split(',');
                            var location = DanmakuLocation.Roll;
                            switch (danmaku[1].ToInt32())
                            {
                                case 7:
                                    location = DanmakuLocation.Position;
                                    break;
                                case 4:
                                    location = DanmakuLocation.Bottom;
                                    break;
                                case 5:
                                    location = DanmakuLocation.Top;
                                    break;
                            }
                            danmakus.Add(new DanmakuModel
                            {
                                Time = double.Parse(danmaku.FirstOrDefault()),
                                Time_s = Convert.ToInt32(double.Parse(danmaku.FirstOrDefault())),
                                Location = location,
                                Size = double.Parse(danmaku.ElementAt(2)),
                                Color = danmaku.ElementAt(3),
                                SendTime = danmaku.ElementAt(4),
                                Pool = danmaku.ElementAt(5),
                                SendID = danmaku.ElementAt(6),
                                RowID = danmaku.ElementAt(7),
                                Text = item.InnerText,
                                Source = item.OuterXml,
                                FromSite = DanmakuSite.Bilibili
                            });
                        }
                        catch (Exception ex)
                        {
                            LogManager.Instance.LogError("ParseBiliBiliXml", ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.Instance.LogError("ParseBiliBiliXml", ex);
            }
            return danmakus;
        }
    }
}